@file:Suppress("RegExpRedundantEscape")

package com.rzico.sbl.ui

import android.Manifest
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.os.VibrationEffect
import android.os.Vibrator
import android.provider.Settings
import androidx.activity.result.ActivityResultLauncher
import androidx.lifecycle.lifecycleScope
import com.fondesa.kpermissions.allGranted
import com.fondesa.kpermissions.anyPermanentlyDenied
import com.fondesa.kpermissions.extension.permissionsBuilder
import com.fondesa.kpermissions.extension.send
import com.jeremyliao.liveeventbus.LiveEventBus
import com.lzy.okgo.model.HttpMethod
import com.rzico.sbl.R
import com.rzico.sbl.databinding.ActivityScanBinding
import com.rzico.sbl.listener.setDelegate
import com.rzico.sbl.model.BaseUrl
import com.rzico.sbl.model.QRMode
import com.rzico.sbl.model.QRType
import com.rzico.sbl.picture.buildSelectionModel
import com.rzico.sbl.picture.callback
import com.rzico.sbl.ui.member.MemberActivity
import com.rzico.sbl.ui.mine.ShopActivity
import com.rzico.sbl.viewmodel.CommonViewModel
import com.xinnuo.common.extend.*
import com.xinnuo.common_ui.base.BaseActivity
import com.xinnuo.common_ui.utils.bindLifeCycle
import com.xinnuo.common_ui.utils.showHintDialog
import com.xinnuo.common_ui.utils.subscribeBySuccess
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import java.util.regex.Pattern


class ScanActivity : BaseActivity(R.layout.activity_scan) {

    private val mBinding by lazy { ActivityScanBinding.bind(getRootView()) }

    private lateinit var mLauncher: ActivityResultLauncher<Intent>

    private var mScanMode = ""
    private var mScanFrom = ""
    private var isFlashlighting = false

    override fun getViewModel() = get<CommonViewModel>()

    override fun initData() {
        initTitle(title = "扫描二维码")

        mScanMode = intent.getExtra("mode")
        mScanFrom = intent.getExtra("from")

        mBinding.scanZxing.setDelegate {
            onScanQRCodeSuccess { result ->
                mBinding.scanZxing.stopCamera()
                vibrate()

                result?.let {
                    // 匹配二维码地址
                    val regex = Pattern
                        .compile("^(http://|https://)(\\w+\\.)+\\w+(:\\d{2,4})?(/\\w*)?/q/\\d+\\.jhtml")
                        .matcher(it)
                        .matches()

                    when {
                        regex -> {
                            var splitValue = ""

                            // 提取二维码内容
                            Pattern
                                .compile("(?<=q\\/).*?(?=\\.jhtml)")
                                .matcher(it)
                                .apply { find().condition { splitValue = group() } }

                            when {
                                // 添加员工
                                QRMode.MODE_01.model in splitValue ->
                                    adminAdd(
                                        splitValue
                                            .replace(
                                                QRMode.MODE_01.model,
                                                ""
                                            )
                                    )
                                // 扫码抢单
                                QRMode.MODE_07.model in splitValue ->
                                    grabOrder(
                                        splitValue
                                            .replace(
                                                QRMode.MODE_07.model,
                                                ""
                                            )
                                    )
                                // 核销优惠券
                                QRMode.MODE_12.model in splitValue -> couponCancel(it)
                                // 会员叫水码
                                QRMode.MODE_14.model in splitValue -> {
                                    when (mScanMode) {
                                        QRType.MEMBER -> bindWater(it)
                                        else -> startActivityEx<MemberActivity>()
                                    }
                                }

                                else -> resetZxing(it)
                            }
                        }
                        // 中午打印机
                        it.startsWith("http://app.zhongwuyun.com") -> {
                            var account = ""
                            var password = ""

                            it.substring(it.indexOf("?") + 1)
                                .split("&")
                                .forEach { item ->
                                    ("m=" in item).condition { account = item.trimStart('m', '=') }
                                    ("p=" in item).condition { password = item.trimStart('p', '=') }
                                }

                            (account.isNotEmpty() && password.isNotEmpty())
                                .conditionElse(
                                    actionTrue = {
                                        when (mScanFrom) {
                                            "shop" -> bindPrint(account, password)
                                            else -> {
                                                startActivityEx<ShopActivity>()
                                                finishView()
                                            }
                                        }
                                    },
                                    actionFalse = { resetZxing("未识别到设备，请重新绑定！") }
                                )
                        }
                        // 自提柜设备编号
                        mScanMode == QRType.CUPBOARD -> {
                            LiveEventBus
                                .get(mScanMode)
                                .post(it.replace(":",""))

                            finishView()
                        }

                        else -> {
                            // 匹配MAC地址，有或无冒号
                            val macRegex = Pattern
                                .compile("^([\\dA-Fa-f]{2}:?){6}\$")
                                .matcher(it)
                                .matches()

                            macRegex.conditionElse(
                                actionTrue = { showToast(it) },
                                actionFalse = { browse(it) }
                            )

                            finishView()
                        }
                    }
                } ?: resetZxing("未识别到二维码！")
            }
        }

        mLauncher = requestForResult { resetZxing() }

        requestPermission()
    }

    override fun initListener() {
        mBinding.apply {
            scanLight.oneClick {
                isFlashlighting =
                    isFlashlighting
                        .conditionElseValue(
                            actionTrue = {
                                scanZxing.closeFlashlight()
                                scanLightHint.text = "轻触照亮"
                                false
                            },
                            actionFalse = {
                                scanZxing.openFlashlight()
                                scanLightHint.text = "轻触关闭"
                                true
                            }
                        )
            }

            scanImg.oneClick {
                buildSelectionModel(
                    isCropEnable = false
                )
                    .callback {
                        onResult {
                            it.notEmpty {
                                scanZxing.decodeQRCode(this[0].compressPath)
                            }
                        }
                    }
            }
        }
    }

    /**
     * 权限申请
     */
    private fun requestPermission() {
        permissionsBuilder(Manifest.permission.CAMERA)
            .build()
            .send {
                when {
                    it.allGranted() -> resetZxing()
                    it.anyPermanentlyDenied() -> showPermissionDialog()
                    else -> finishView()
                }
            }
    }

    /**
     * 权限禁止显示后提示操作
     */
    private fun showPermissionDialog() {
        showHintDialog(
            title = "提示",
            hint = "相机权限被禁止开启，请打开权限设置页面手动开启",
            sure = "去设置",
            cancel = "再想想",
            isForced = true,
            onCancel = ::finishView,
            onSure = {
                mLauncher.launch(
                    Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
                        .apply {
                            data = Uri.parse("package:$packageName")
                        }
                )
            }
        )
    }

    /**
     * 绑定打印机
     */
    private fun bindPrint(account: String, pwd: String) {
        getViewModel()
            .requestBind(
                requestUrl = BaseUrl.shopPnt,
                params = arrayOf(
                    "shopId" to intent.getExtra("shopId"),
                    "u" to account,
                    "p" to pwd
                )
            )
            .bindLifeCycle(getLifecycleOwner())
            .subscribeBySuccess(
                event = getViewModel(),
                onFailed = { _, _ -> resetZxing("") },
                onSuccess = {
                    showToast("打印机绑定成功！")

                    // 刷新店铺列表
                    LiveEventBus
                        .get("shopList")
                        .post("$account,$pwd")

                    finishView()
                }
            )
    }

    /**
     * 添加员工
     */
    private fun adminAdd(code: String) {
        getViewModel()
            .requestBind(
                isLoading = true,
                requestUrl = BaseUrl.mngAdd,
                params = arrayOf("code" to code)
            )
            .bindLifeCycle(getLifecycleOwner())
            .subscribeBySuccess(
                event = getViewModel(),
                onFailed = { _, _ -> resetZxing("") },
                onSuccess = {
                    showToast("添加员工成功！")

                    (intent.getExtra("status") == "list")
                        .condition {
                            // 更新员工列表
                            LiveEventBus
                                .get("masterList")
                                .post("refresh")
                        }

                    finishView()
                }
            )
    }

    /**
     * 扫描抢单
     */
    private fun grabOrder(orderSn: String) {
        getViewModel()
            .requestBind(
                isLoading = true,
                requestUrl = BaseUrl.orderGrab,
                params = arrayOf("sn" to orderSn)
            )
            .bindLifeCycle(getLifecycleOwner())
            .subscribeBySuccess(
                event = getViewModel(),
                onFailed = { _, _ -> resetZxing("") },
                onSuccess = {
                    showToast("扫描抢单成功！")
                    finishView()
                }
            )
    }

    /**
     * 核销优惠券
     */
    private fun couponCancel(code: String) {
        getViewModel()
            .requestBind(
                isLoading = true,
                requestUrl = BaseUrl.mngCouponCan,
                requestMethod = HttpMethod.GET,
                params = arrayOf("code" to code)
            )
            .bindLifeCycle(getLifecycleOwner())
            .subscribeBySuccess(
                event = getViewModel(),
                onFailed = { _, _ -> resetZxing("") },
                onSuccess = {
                    showToast("核销券成功！")

                    finishView()
                }
            )
    }

    /**
     * 会员绑定/解绑叫水码
     */
    private fun bindWater(code: String) {
        val status = intent.getExtra("status")

        getViewModel()
            .requestBind(
                isLoading = true,
                requestUrl = conditionIf(
                    status == "bind",
                    BaseUrl.codeBind,
                    BaseUrl.codeDel
                ),
                params = arrayOf(
                    "memberId" to intent.getExtra("memberId"),
                    "code" to code
                )
            )
            .bindLifeCycle(getLifecycleOwner())
            .subscribeBySuccess(
                event = getViewModel(),
                onFailed = { _, _ -> resetZxing("") },
                onSuccess = {
                    showToast(
                        conditionIf(
                            status == "bind",
                            "叫水码绑定成功！",
                            "叫水码解绑成功！"
                        )
                    )

                    finishView()
                }
            )
    }

    override fun onStart() {
        super.onStart()
        mBinding.scanZxing.apply {
            startCamera() //打开后置摄像头开始预览，但是并未开始识别
            startSpotAndShowRect() //显示扫描框，并开始识别
        }
    }

    override fun onStop() {
        super.onStop()
        mBinding.scanZxing.stopCamera() //关闭摄像头预览，并且隐藏扫描框
    }

    override fun onDestroy() {
        super.onDestroy()
        mBinding.scanZxing.onDestroy() //销毁二维码扫描控件
    }

    /**
     * 扫描震动
     *
     * 注：当打开camera时，震动可能无效
     */
    @SuppressLint("NewApi")
    private fun vibrate() {
        val vibrator = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator

        (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
            .conditionElse(
                actionTrue = {
                    vibrator.vibrate(
                        VibrationEffect
                            .createOneShot(
                                200,
                                VibrationEffect.DEFAULT_AMPLITUDE
                            )
                    )
                },
                actionFalse = {
                    @Suppress("DEPRECATION")
                    vibrator.vibrate(200)
                }
            )
    }

    /**
     * 重置扫描
     */
    private fun resetZxing(hint: String = "") {
        hint.notEmpty { showToast(this) }

        lifecycleScope.launch {
            delay(2000)

            isFlashlighting = false
            mBinding.scanLightHint.text = "轻触照亮"
            mBinding.scanZxing.startCamera()
            mBinding.scanZxing.startSpotAndShowRect()
        }
    }

}